网络安全第二次实验(第三次作业) 陈实 SA17011008


1
SA17011008 陈实 2017年10月10日  实验 2

[TOC]

#一、实验要求

1
修改例程cryptoDemo.cpp为encfile.cpp,从命令行接受参数3个字符串类型的参数:参数1,参数2,参数3。参数1=enc表示加密,参数1=dec表示解密;参数2为待加密、解密的文件;参数3为密码。

#二、实验准备

1
2
3
VirtualBox
Ubuntu16.04
gcc

安装openssl库,使用命令:

1
sudo apt-get install libssl-dev

此处输入图片的描述

#三、实验过程

##3.1 试验cryptoDemo.cpp效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//程序源码
// cryptoDemo.cpp : Defines the entry point for the console application.
// Windows: cl cryptoDemo.cpp
// Linux: gcc -o cryptoDemo cryptoDemo.cpp -lcrypto

#include <memory.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "openssl/aes.h"

#pragma comment(lib,"libeay32.lib")

void testAes(char inString[], int inLen, char passwd[], int pwdLen)
{
int i,j, len, nLoop, nRes;
char enString[1024];
char deString[1024];

unsigned char buf[16];
unsigned char buf2[16];
unsigned char aes_keybuf[32];
AES_KEY aeskey;

// 准备32字节(256位)的AES密码字节
memset(aes_keybuf,0x90,32);
if(pwdLen<32){ len=pwdLen; } else { len=32;}
for(i=0;i<len;i++) aes_keybuf[i]=passwd[i];
// 输入字节串分组成16字节的块
nLoop=inLen/16; nRes = inLen%16;
// 加密输入的字节串
AES_set_encrypt_key(aes_keybuf,256,&aeskey);
for(i=0;i<nLoop;i++){
memset(buf,0,16);
for(j=0;j<16;j++) buf[j]=inString[i*16+j];
AES_encrypt(buf,buf2,&aeskey);
for(j=0;j<16;j++) enString[i*16+j]=buf2[j];
}
if(nRes>0){
memset(buf,0,16);
for(j=0;j<nRes;j++) buf[j]=inString[i*16+j];
AES_encrypt(buf,buf2,&aeskey);
for(j=0;j<16;j++) enString[i*16+j]=buf2[j];
//puts("encrypt");
}
enString[i*16+j]=0;
// 密文串的解密
AES_set_decrypt_key(aes_keybuf,256,&aeskey);
for(i=0;i<nLoop;i++){
memset(buf,0,16);
for(j=0;j<16;j++) buf[j]=enString[i*16+j];
AES_decrypt(buf,buf2,&aeskey);
for(j=0;j<16;j++) deString[i*16+j]=buf2[j];
}
if(nRes>0){
memset(buf,0,16);
for(j=0;j<16;j++) buf[j]=enString[i*16+j];
AES_decrypt(buf,buf2,&aeskey);
for(j=0;j<16;j++) deString[i*16+j]=buf2[j];
//puts("decrypt");
}
deString[i*16+nRes]=0;
//比较解密后的串是否与输入的原始串相同
if(memcmp(inString,deString,strlen(inString))==0)
{ printf("test success\r\n");} else { printf("test fail\r\n");}
printf("The original string is:\n %s ", inString);
printf("The encrypted string is:\n %s ", enString);
printf("The decrypted string is:\n %s ", deString);
}

int main(int argc, char* argv[])
{
char inString[] = "This is a sample. I am a programer.\n";
char passwd[] = "0123456789ABCDEFGHIJK";

testAes(inString, strlen(inString), passwd, strlen(passwd));

return 0;
}

利用gcc编译,并执行

1
2
gcc -o cryp cryptoDemo.cpp -lcrypto
./cryp

此处输入图片的描述

##3.2 改写原demo

  • 修改例程cryptoDemo.cpp为encfile.cpp,
  • 从命令行接受参数3个字符串类型的参数:参数1,参数2,参数3。
  • 参数1=enc表示加密,参数1=dec表示解密;参数2为待加密、解密的文件;参数3为密码。

修改部分:拆解原demo,加上文件读写即可,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// cryptoDemo.cpp : Defines the entry point for the console application.
// Windows: cl cryptoDemo.cpp
// Linux: gcc -o cryptoDemo cryptoDemo.cpp -lcrypto
// Linux: gcc -o encfile encfile.cpp -lcrypto
// chen SA17011008

#include <memory.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <openssl/aes.h>

#pragma comment(lib,"libeay32.lib")


void encrypt(char *filename, char passwd[], int pwdLen) //加密
{
char inString[1024];
char enFile[1024]; //加密后的文件名
strcpy(enFile,filename);
strcat(enFile,"_encrypt"); //加密后的文件名

//文件读取
FILE *fp=fopen(filename,"r");
if(fp==NULL)
{
printf("文件%s打开错误\n",filename);
fclose(fp);
return;
}
char c=fgetc(fp); //从fp所指文件的当前指针位置读取一个字符
int i=0;
while(c!=EOF)
{
inString[i++]=c;
c=fgetc(fp);
}
inString[i]=0; //输入结束符
fclose(fp);


//加密(demo部分代码)
int j, len, nLoop, nRes;
char enString[1024];

unsigned char buf[16];
unsigned char buf2[16];
unsigned char aes_keybuf[32];
AES_KEY aeskey;

int inLen=strlen(inString); //原始字符串的长度
// 准备32字节(256位)的AES密码字节
memset(aes_keybuf,0x90,32);
if(pwdLen<32){ len=pwdLen; } else { len=32;}
for(i=0;i<len;i++) aes_keybuf[i]=passwd[i];
// 输入字节串分组成16字节的块
nLoop=inLen/16; nRes = inLen%16;
// 加密输入的字节串
AES_set_encrypt_key(aes_keybuf,256,&aeskey);
for(i=0;i<nLoop;i++){
memset(buf,0,16);
for(j=0;j<16;j++) buf[j]=inString[i*16+j];
AES_encrypt(buf,buf2,&aeskey);
for(j=0;j<16;j++) enString[i*16+j]=buf2[j];
}
if(nRes>0){
memset(buf,0,16);
for(j=0;j<nRes;j++) buf[j]=inString[i*16+j];
AES_encrypt(buf,buf2,&aeskey);
for(j=0;j<16;j++) enString[i*16+j]=buf2[j];
//puts("encrypt");
}
enString[i*16+j]=0;

//写入文件
FILE *fpw=fopen(enFile,"w");
if(fpw==NULL)
{
printf("不能写入%s\n",enFile);
fclose(fpw);
return;
}
int len1=strlen(enString);
for(int i=0;i<len1;i++)
{
fputc(enString[i],fpw);
}
fclose(fpw);
}


void decrypt(char *filename, char passwd[], int pwdLen) //解密
{
char enString[1024]; //从文件中读取的密文串
char deFile[1024]; //解密后的文件名
strcpy(deFile,filename);
strcat(deFile,"_decrypt"); //解密后的文件名

//文件读取
FILE *fp=fopen(filename,"r");
if(fp==NULL)
{
printf("文件%s打开错误\n",filename);
fclose(fp);
return;
}
char c=fgetc(fp); //从fp所指文件的当前指针位置读取一个字符
int i=0;
while(c!=EOF)
{
enString[i++]=c;
c=fgetc(fp);
}
enString[i]=0; //输入结束符
fclose(fp);

//解密
int j, len, nLoop, nRes;
char deString[1024]; //解密后的字符串

unsigned char buf[16];
unsigned char buf2[16];
unsigned char aes_keybuf[32];
AES_KEY aeskey;

// 准备32字节(256位)的AES密码字节
memset(aes_keybuf,0x90,32);
if(pwdLen<32){ len=pwdLen; } else { len=32;}
for(i=0;i<len;i++) aes_keybuf[i]=passwd[i];

int inLen=strlen(enString);
// 密文字节串分组成16字节的块
nLoop=inLen/16; nRes = inLen%16;

// 密文串的解密
AES_set_decrypt_key(aes_keybuf,256,&aeskey);
for(i=0;i<nLoop;i++){
memset(buf,0,16);
for(j=0;j<16;j++) buf[j]=enString[i*16+j];
AES_decrypt(buf,buf2,&aeskey);
for(j=0;j<16;j++) deString[i*16+j]=buf2[j];
}
if(nRes>0){
memset(buf,0,16);
for(j=0;j<16;j++) buf[j]=enString[i*16+j];
AES_decrypt(buf,buf2,&aeskey);
for(j=0;j<16;j++) deString[i*16+j]=buf2[j];
//puts("decrypt");
}
deString[i*16+nRes]=0;

//写入文件
FILE *fpw=fopen(deFile,"w");
if(fpw==NULL)
{
printf("不能写入%s.\n",deFile);
fclose(fpw);
return;
}
int len1=strlen(deString);
for(i=0;i<len1;i++)
{
fputc(deString[i],fpw);
}
fclose(fpw);
}


int main(int argc, char* argv[])
{
// 检测参数是否为4个
if(argc!=4)
printf("Error format!\n");

//获取参数
char *type=argv[1];
char *filename=argv[2];
char *passwd=argv[3];

//加密&解密
if(strcmp(type,"enc")==0)
encrypt(filename,passwd,strlen(passwd));
else if(strcmp(type,"dec")==0)
decrypt(filename,passwd,strlen(passwd));
else
printf("parameter error!\n");

return 0;
}

编译encfile.cpp

写完之后,在终端下,执行下面的操作,进行编译,生成encfile

1
gcc -o encfile encfile.cpp -lcrypto

此处输入图片的描述

明文文件内容如下:
此处输入图片的描述

执行加密

1
./encfile enc file 0123456789ABCDEFGHIJK

密文文件内容如下:
此处输入图片的描述

执行解密

1
./encfile dec file_encrypt 0123456789ABCDEFGHIJK

此处输入图片的描述

可以看出,加密前后的内容是一致的。

#四、实验心得
通过这次试验,对 aes 加密解密有了简单的了解,并简单实验了加密和解密过程,将处理后的信息保存下来。通过这次实验自己亲手体会了其中加密和解密的过程,收获很大。